package com.reach.redis.aspect;

import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

import com.google.gson.Gson;
import com.reach.redis.manager.SpringContextUtil;


public class CacheAspect {
	
	private static final Logger logger = LoggerFactory.getLogger(CacheAspect.class);
	
	private static final Executor executor = Executors.newSingleThreadExecutor();
	
	
    public Object readCache(String key) {
    	try {
    		
    		//Assert.notEmpty(key, "'key' must not be empty");
    		if(logger.isDebugEnabled()) {
    			logger.debug("Cache key is {}.",String.valueOf(key));
    		}
    		@SuppressWarnings("unchecked")
			RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) SpringContextUtil.getBean("redis");
    		return redisTemplate.opsForValue().get(key);
    	}catch(Exception e ) {
    		logger.error(e.getMessage());
    	}
    	return null;
    }
    
    public boolean writeCache(Object value,String  key,int expire) {
    	try {
    		//Assert.notEmpty(key, "'key' must not be empty");
    		if(logger.isDebugEnabled()) {
    			Gson gson = new Gson();
    			logger.debug("Cache key is {}:{}.",String.valueOf(key),gson.toJson(value));
    		}
    		@SuppressWarnings("unchecked")
			RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) SpringContextUtil.getBean("redis");
    		if(expire > 0) {
    			redisTemplate.opsForValue().set(key,value,expire,TimeUnit.SECONDS);
    		}else {
    			redisTemplate.opsForValue().set(key,value);
    		}
    		return true;
    	}catch(Exception e ) {
    		logger.error(e.getMessage());
    	}
    	return false;
    }
    
    public boolean delete(String module,boolean async,String... key) {
    	try {
	    	if(key == null || key.length <=0) {
	    		return false;
	    	}
	    	if(async) {
	    		executor.execute(new CacheThread(module,key));
	    	}else {
	    		delete(module, key);
	    	}
    	}catch(Exception e) {
    		logger.error(e.getMessage());
    	}
    	return false;
    }
    
    private void delete(final String module,final String... keys) {
    	@SuppressWarnings("unchecked")
		RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) SpringContextUtil.getBean("redis");
    	redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection) {
					for(String value : keys) {
						Set<byte[]> keys = connection.keys(("*"+value + "*").getBytes());
						for(byte[] by : keys){
							String str = new String(by,StandardCharsets.UTF_8);
							if(str.startsWith(module)) {
								 connection.del(by);
								 if(logger.isDebugEnabled()) {
									 logger.debug("Delete reids key is {}.",str);
								 }
				    		}
						}
					}
					return null;
			}

		});
    }
    
    class CacheThread implements Runnable{
    	private String module;
    	private String[] key;
    	
    	public CacheThread(String module,String... key) {
    		this.module = module;
    		this.key = key;
    	}
		@Override
		public void run() {
			delete(module, key);
		}
    	
    }
    
 
}